package org.umlviewer.xmiparser;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.umlviewer.model.UmlDiagram;
import org.jdom2.Document;
import org.jdom2.JDOMException;
import org.jdom2.input.SAXBuilder;
import org.jdom2.Element;
import org.umlviewer.model.Constants;
import org.umlviewer.model.DiagramElement;
import org.jdom2.*;
import org.jdom2.xpath.XPath;

/**
 *
 * @author Rafa
 */
public class XmiDocument {

    //el archivo xmi que se parsea
    private Document xml = null;
    //ruta fisica del archivo
    private String filepath ;
    //parser del xml
    private SAXBuilder builder;
    //nodo raiz
    private Element root;
    private XmiParser parser;
    //si el xmi posee el nodo de las posiciones
    private boolean xmiExtension;
    //manejo del log
    private static final Logger logger =  Logger.getLogger(XmiDocument.class.getName());
    
    public XmiDocument()
    {
        filepath  = "";
        builder =  new SAXBuilder();
        xmiExtension = false;
    }
    
    private void loadFile() throws XmiParseError, IOException
    {
        FileInputStream entrada=null;
        try{
             entrada = new FileInputStream(filepath);
        }catch(FileNotFoundException e){
            logger.log(Level.SEVERE,"Archivo no encontrado ",e.getLocalizedMessage());
        }
        try {
            // se cargar el archivo a memoria
            xml = builder.build(entrada);
        } catch (JDOMException ex) {
            logger.log(Level.SEVERE, null, ex);
            throw new XmiParseError("Error al procesar el archivo "+ ex.getLocalizedMessage());                    
        }
    }

    public UmlDiagram getUmlDiagram() throws XmiParseError, IOException, UnsupportedXmiVersion{
        UmlDiagram retuml = null;
        String xmiversion="";
        String geostr = "";
        String id, strx, stry;
        String[] coordenadas;
        DiagramElement elemento;
        Attribute attversion = null;
        //namespace for reed xmi attributes
        Namespace ns;
        int x, y;
        
        loadFile();
        
        if (xml != null) {
            root = xml.getRootElement();
            //obtener el namespace para los elementos xmi
            ns = root.getNamespace("xmi") != null ? root.getNamespace("xmi") : Constants.XMINAMESPACE;
            
            //para la version 2.1
            attversion = root.getAttribute("version", ns);
            if(attversion == null)
                attversion = root.getAttribute("xmi.version"); //version 1.1 - 1.3
            
            if(attversion !=null)
                xmiversion = attversion.getValue();
            
            logger.log(Level.INFO, "version xmi: {0}", xmiversion);

            parser = FactoryXmiParser.getXmiParser(xmiversion);
            if (parser != null) {
                parser.setXmiNamespace(ns);
                retuml = parser.getUmlDiagram(root);
                //asignar coordenadas x,y para los elementos;; EnterpriseArquitect
                if (retuml != null) {
                    Element extension = root.getChild("Extension", ns);
                    //si el xmi contiene el nodo de las posiciones
                    if (extension != null) {
                        xmiExtension = true;
                        try {
                            List<Element> geometrias = (List<Element>) XPath.selectNodes(extension, "diagrams/diagram/elements/element");
                            for (Element egeometry : geometrias) {
                                geostr = egeometry.getAttributeValue("geometry");
                                id = egeometry.getAttributeValue("subject");
                                coordenadas = geostr.split(";");

                                strx = coordenadas[0].substring(coordenadas[0].indexOf('=') + 1, coordenadas[0].length());
                                stry = coordenadas[1].substring(coordenadas[1].indexOf('=') + 1, coordenadas[1].length());

                                if (strx.equals("")) {
                                    strx = "0";
                                }
                                if (stry.equals("")) {
                                    stry = "0";
                                }

                                x = Integer.parseInt(strx);
                                y = Integer.parseInt(stry);

                                //System.out.println("X: "+x+"  Y: "+y);

                                elemento = retuml.getElmentById(id);
                                if (elemento != null) {
                                    elemento.setPosX(x);
                                    elemento.setPosY(y);
                                }

                            }
                        } catch (JDOMException ex) {
                            logger.log(Level.SEVERE, null, ex);
                            throw new XmiParseError(ex.getLocalizedMessage());
                        }
                    }
                }
            } else {
                logger.log(Level.SEVERE,"No se instancio el parser, version XMI no soportada");
                throw new UnsupportedXmiVersion("version XMI no soportada");
            }

        }
        return retuml;
    }

    public String getFilepath() {
        return filepath;
    }

    public void setFilepath(String filepath) {
        this.filepath = filepath;
    }
    
    public boolean hasXmiExtension()
    {
        return xmiExtension;
    }
    
    
}
